package com.qs.cwams.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;

import com.qs.common.framework.dto.QsResult;
import com.qs.common.framework.util.ConvertUtil;
import com.qs.common.framework.util.RedisUtils;
import com.qs.cwams.mapper.*;
import com.qs.cwams.pojo.domain.*;
import com.qs.cwams.pojo.view.*;
import com.qs.cwams.service.AtteRecordService;
import com.qs.cwams.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

/**
 * @author suncheng
 */
@Service
public class AtteRecordServiceImpl implements AtteRecordService {
    private static final Logger logger = LoggerFactory.getLogger(AtteRecordService.class);

    private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Value("${export.path}")
    private String exportPath;

    @Autowired
    private AtteRecordMapper atteRecordMapper;
    @Autowired
    private AtteConfigMapper atteConfigMapper;
    @Autowired
    private AtteRuleMapper atteRuleMapper;
    @Autowired
    private ApplyMapper applyMapper;
    @Autowired
    private ApplyDetailMapper applyDetailMapper;
    @Autowired
    private RedisUtils redisUtils;

    private void specialLateRule(AtteRecordDO record, TimeSlot work, AtteDailyTime daily) {
        LocalDateTime startTime = LocalDateTime.ofInstant(record.getStartTime().toInstant(), ZoneId.systemDefault());
        LocalDateTime endTime = LocalDateTime.ofInstant(record.getEndTime().toInstant(), ZoneId.systemDefault());
        // 若当天下班打卡时间超过22点且迟到小于60分钟, 视为正常
        long minutes = Duration.between(work.getStartTime(), startTime).toMinutes();
        if (minutes <= 60 && minutes > 0 && endTime.isAfter(LocalDateTime.of(daily.getDate(), LocalTime.of(22, 0)))) {
            record.setResult(AtteResult.ok.getResult());
        }
    }

    private void setResult(AtteRecordDO record, TimeSlot work, AtteDailyTime daily) {
        if (work == null) {
            List<TimeSlot> slots = daily.getWorkTime().stream().map(item -> new TimeSlot(item.getStartTime(), item.getEndTime()))
                    .sorted(Comparator.comparingLong(TimeSlot::getStart)).collect(Collectors.toList());
            // 无上班时间视为全天假
            record.setResult(AtteResult.ok.getResult());
            record.setStartTime(Date.from(slots.get(0).getStartTime().atZone(ZoneId.systemDefault()).toInstant()));
            record.setEndTime(Date.from(slots.get(slots.size() - 1).getEndTime().atZone(ZoneId.systemDefault()).toInstant()));
            return;
        }

        if (record.getId() == null || (record.getStartTime() == null && record.getEndTime() == null)) {
            // 无记录视为无考勤
            record.setResult(AtteResult.none.getResult());
            return;
        }

        LocalDateTime startTime = LocalDateTime.ofInstant(record.getStartTime().toInstant(), ZoneId.systemDefault());
        LocalDateTime endTime = LocalDateTime.ofInstant(record.getEndTime().toInstant(), ZoneId.systemDefault());
        LocalDateTime startRule = work.getStartTime();
        LocalDateTime endRule = work.getEndTime();
        if (startTime.isBefore(startRule.plusMinutes(1)) && endTime.isAfter(endRule.plusSeconds(-1))) {
            // 正常
            record.setResult(AtteResult.ok.getResult());
        } else if (startTime.isBefore(startRule.plusMinutes(1)) &&
                (endTime.isBefore(endRule.plusSeconds(-1)) || endTime.equals(endRule.plusSeconds(-1)))) {
            if (endTime.isBefore(startRule.plusMinutes(1))) {
                // 若上班正常下班忘打卡则为下班忘打卡
                record.setResult(AtteResult.forgotP.getResult());
            } else {
                // 否则视为早退
                record.setResult(AtteResult.leave.getResult());
            }
        } else if ((startTime.isAfter(startRule.plusMinutes(1)) || startTime.equals(startRule.plusMinutes(1))) &&
                endTime.isAfter(endRule.plusSeconds(-1))) {
            if (startTime.isAfter(endRule.plusSeconds(-1))) {
                // 若上班忘打卡下班正常则为上班忘打卡
                record.setResult(AtteResult.forgotA.getResult());
            } else {
                // 否则视为迟到
                record.setResult(AtteResult.late.getResult());
                // 特殊迟到规则
                specialLateRule(record, work, daily);
            }
        } else {
            if (startTime.equals(endTime)) {
                //相同卡视为迟到+下班忘打卡
                record.setResult(AtteResult.late.getResult() + "+" + AtteResult.forgotP.getResult());
            } else {
                //不同卡视为迟到+早退
                record.setResult(AtteResult.late.getResult() + "+" + AtteResult.leave.getResult());
            }
        }
    }

    private double getHours(List<ApplyDetailDO> details) {
        AtomicLong minutes = new AtomicLong(0);
        details.forEach(detail -> {
            LocalDateTime start = LocalDateTime.ofInstant(detail.getStartTime().toInstant(), ZoneId.systemDefault());
            LocalDateTime end = LocalDateTime.ofInstant(detail.getEndTime().toInstant(), ZoneId.systemDefault());
            minutes.addAndGet(Duration.between(start, end).toMinutes());
        });
        return minutes.doubleValue() / 60;
    }

    private void getApplyHours(AtteCalcVO atteCalcVO) {
        List<ApplyDetailDO> details = applyDetailMapper.selectList(new LambdaQueryWrapper<ApplyDetailDO>()
                .eq(ApplyDetailDO::getUserId, atteCalcVO.getUserId())
                .eq(ApplyDetailDO::getYear, atteCalcVO.getYear())
                .eq(ApplyDetailDO::getMonth, atteCalcVO.getMonth()));

        if (details.size() > 0) {
            List<ApplyDetailDO> leaveTotalList = new ArrayList<>();
            List<ApplyDetailDO> sickTotalList = new ArrayList<>();
            List<ApplyDetailDO> annualTotalList = new ArrayList<>();
            List<ApplyDetailDO> marriageTotalList = new ArrayList<>();
            List<ApplyDetailDO> funeralTotalList = new ArrayList<>();
            List<ApplyDetailDO> maternityTotalList = new ArrayList<>();
            List<ApplyDetailDO> paternityTotalList = new ArrayList<>();
            List<ApplyDetailDO> compensatoryTotalList = new ArrayList<>();
            List<ApplyDetailDO> goOutTotalList = new ArrayList<>();
            List<ApplyDetailDO> addTotalList = new ArrayList<>();
            List<ApplyDetailDO> businessTotalList = new ArrayList<>();
            details.forEach(detail -> {
                switch (detail.getType()) {
                    case 0:
                        leaveTotalList.add(detail);
                        break;
                    case 1:
                        sickTotalList.add(detail);
                        break;
                    case 2:
                        annualTotalList.add(detail);
                        break;
                    case 3:
                        marriageTotalList.add(detail);
                        break;
                    case 4:
                        funeralTotalList.add(detail);
                        break;
                    case 5:
                        maternityTotalList.add(detail);
                        break;
                    case 6:
                        paternityTotalList.add(detail);
                        break;
                    case 8:
                        compensatoryTotalList.add(detail);
                        break;
                    case 9:
                        goOutTotalList.add(detail);
                        break;
                    case 10:
                        addTotalList.add(detail);
                        break;
                    case 11:
                        businessTotalList.add(detail);
                        break;
                }
            });
            atteCalcVO.setLeaveTotal(getHours(leaveTotalList));
            atteCalcVO.setSickTotal(getHours(sickTotalList));
            atteCalcVO.setAnnualTotal(getHours(annualTotalList));
            atteCalcVO.setMarriageTotal(getHours(marriageTotalList));
            atteCalcVO.setFuneralTotal(getHours(funeralTotalList));
            atteCalcVO.setMaternityTotal(getHours(maternityTotalList));
            atteCalcVO.setPaternityTotal(getHours(paternityTotalList));
            atteCalcVO.setCompensatoryTotal(getHours(compensatoryTotalList));
            atteCalcVO.setGoOutTotal(getHours(goOutTotalList));
            atteCalcVO.setAddTotal(getHours(addTotalList));
            atteCalcVO.setBusinessTotal(getHours(businessTotalList));
        } else {
            atteCalcVO.setLeaveTotal(0D);
            atteCalcVO.setSickTotal(0D);
            atteCalcVO.setAnnualTotal(0D);
            atteCalcVO.setMarriageTotal(0D);
            atteCalcVO.setFuneralTotal(0D);
            atteCalcVO.setMaternityTotal(0D);
            atteCalcVO.setPaternityTotal(0D);
            atteCalcVO.setCompensatoryTotal(0D);
            atteCalcVO.setGoOutTotal(0D);
            atteCalcVO.setAddTotal(0D);
            atteCalcVO.setBusinessTotal(0D);
        }
    }

    private TimeSlot getWorkTimeSlot(AtteRecordDO record, AtteDailyTime daily) {
        List<ApplyDetailDO> details = applyDetailMapper.selectList(new LambdaQueryWrapper<ApplyDetailDO>()
                .eq(ApplyDetailDO::getUserId, record.getUserId())
                .eq(ApplyDetailDO::getYear, record.getAtteYear())
                .eq(ApplyDetailDO::getMonth, record.getAtteMonth())
                .eq(ApplyDetailDO::getDay, record.getAtteDay()));

        if (details.size() == 0) {
            List<TimeSlot> slots = daily.getWorkTime().stream().map(item -> new TimeSlot(item.getStartTime(), item.getEndTime()))
                    .sorted(Comparator.comparingLong(TimeSlot::getStart)).collect(Collectors.toList());
            if (slots.size() > 0) {
                LocalDateTime start = slots.get(0).getStartTime();
                LocalDateTime end = slots.get(slots.size() - 1).getEndTime();
                return new TimeSlot(start, end);
            } else {
                return null;
            }
        } else {
            List<TimeSlot> slots = details.stream().map(item -> new TimeSlot(item.getStartTime().getTime(), item.getEndTime().getTime()))
                    .sorted(Comparator.comparingLong(TimeSlot::getStart)).collect(Collectors.toList());

            List<TimeSlot> newWorkTime = new ArrayList<>();
            daily.getWorkTime().forEach(time -> {
                Optional<TimeSlot> optional = slots.stream().filter(time::overlapsWith).findAny();
                if (optional.isPresent()) {
                    List<TimeSlot> list = time.exclude(optional.get());
                    if (list.size() > 0) {
                        newWorkTime.addAll(list);
                    }
                } else {
                    newWorkTime.add(time);
                }
            });
            if (newWorkTime.size() > 0) {
                newWorkTime.sort(Comparator.comparingLong(TimeSlot::getStart));
                LocalDateTime start = newWorkTime.get(0).getStartTime();
                LocalDateTime end = newWorkTime.get(newWorkTime.size() - 1).getEndTime();
                return new TimeSlot(start, end);
            } else {
                return null;
            }
        }
    }

    @Override
    public QsResult queryStatistic(AtteStatisticVO atteStatisticVO) {
        if (atteStatisticVO.getYear() == null || atteStatisticVO.getMonth() == null) {
            return QsResult.fail(400, "参数错误");
        }

        List<AtteRecordDO> recordDOs = atteRecordMapper.selectList(new LambdaQueryWrapper<AtteRecordDO>()
                .eq(AtteRecordDO::getAtteYear, atteStatisticVO.getYear())
                .eq(AtteRecordDO::getAtteMonth, atteStatisticVO.getMonth())
                .eq(atteStatisticVO.getUserId() != null, AtteRecordDO::getUserId, atteStatisticVO.getUserId()));
        List<AtteRecordVO> records = ConvertUtil.listCopy(recordDOs, AtteRecordVO.class);
        Map<Integer, List<AtteRecordVO>> dateMap = records.stream().collect(Collectors.groupingBy(AtteRecordVO::getAtteDay));
        return QsResult.ok().setResult(dateMap);
    }

    @Override
    public Double queryTotal(AtteDateVO atteDateVO) {
        LocalDate now = LocalDate.of(atteDateVO.getYear(), atteDateVO.getMonth(), 1);
        LocalDate firstDay = now.with(TemporalAdjusters.firstDayOfMonth());
        LocalDate lastDay = now.with(TemporalAdjusters.lastDayOfMonth());
        long minutes = 0L;
        for (int i = 0; i < lastDay.getDayOfMonth(); i++) {
            LocalDate current = firstDay.plusDays(i);
            AtteDailyTime daily = new AtteDailyTime(current);
            if (daily.getWorkTime().size() > 0) {
                for (TimeSlot timeSlot : daily.getWorkTime()) {
                    minutes += Duration.between(timeSlot.getStartTime(), timeSlot.getEndTime()).toMinutes();
                }
            }
        }
        return (double) minutes / 60;
    }

    @Override
    public List<AtteCalcVO> calc(AtteCalcVO atteCalcVO) {
        LocalDate now = LocalDate.now();
        // 查询当月非当天的考勤记录
        List<AtteRecordDO> records = atteRecordMapper.selectList(new LambdaQueryWrapper<AtteRecordDO>()
                .eq(AtteRecordDO::getAtteYear, atteCalcVO.getYear())
                .eq(AtteRecordDO::getAtteMonth, atteCalcVO.getMonth())
                .eq(atteCalcVO.getUserId() != null, AtteRecordDO::getUserId, atteCalcVO.getUserId()));
        Map<Integer, List<AtteRecordDO>> dayMap = records.stream().filter(item -> item.getAtteYear() != now.getYear() ||
                        item.getAtteMonth() != now.getMonth().getValue() || item.getAtteDay() != now.getDayOfMonth())
                .collect(Collectors.groupingBy(AtteRecordDO::getAtteDay));

        int times = 0;
        AtteConfigDO lateTimesConfig = atteConfigMapper.selectOne(new LambdaQueryWrapper<AtteConfigDO>()
                .eq(AtteConfigDO::getConfigCode, "LateTimes"));
        if (lateTimesConfig != null) {
            times = Integer.parseInt(lateTimesConfig.getConfigValue());
        }

        Map<Long, AtteCalcVO> users = new HashMap<>();
        Map<Long, Integer> late = new HashMap<>();
        int baseLateTimes = times;
        dayMap.forEach((k, v) -> {
            AtteDailyTime daily = new AtteDailyTime(LocalDate.of(atteCalcVO.getYear(), atteCalcVO.getMonth(), k));
            // daily.getWorkTime()为工作时间段
            if (daily.getWorkTime().size() > 0) {
                v.sort(Comparator.comparing(AtteRecordDO::getAtteDay));
                v.forEach(record -> {
                    // 判断是否请假
                    TimeSlot workTime = getWorkTimeSlot(record, daily);
                    if (workTime != null) {
                        int availableTimes = baseLateTimes;
                        if (late.containsKey(record.getUserId())) {
                            availableTimes = late.get(record.getUserId());
                        }

                        AtteCalcVO calcVO;
                        if (users.containsKey(record.getUserId())) {
                            calcVO = users.get(record.getUserId());
                        } else {
                            calcVO = new AtteCalcVO();
                            calcVO.setUserId(record.getUserId());
                            calcVO.setUserName(redisUtils.getUserName(record.getUserId()));
                            calcVO.setYear(atteCalcVO.getYear());
                            calcVO.setMonth(atteCalcVO.getMonth());
                            calcVO.setAbsenceTotal(0L);
                            calcVO.setExceptDay(new ArrayList<>());
                            users.put(record.getUserId(), calcVO);
                        }

                        if (AtteResult.containExcept(record.getResult())) {
                            // 收集日常考勤信息
                            AtteRecordVO exceptRecord = ConvertUtil.copy(record, AtteRecordVO.class);
                            calcVO.getExceptDay().add(exceptRecord);
                            // 计算异常考勤的缺勤时间
                            long minutes = 0;
                            LocalDateTime startTime = record.getStartTime() == null ? workTime.getEndTime() :
                                    LocalDateTime.ofInstant(record.getStartTime().toInstant(), ZoneId.systemDefault());
                            if (startTime.isAfter(workTime.getStartTime())) {
                                minutes = Duration.between(workTime.getStartTime(), startTime).toMinutes();
                            }

                            if (minutes > 0) {
                                // 迟到免除次数判断
                                if (availableTimes > 0 && minutes < 15) {
                                    availableTimes--;
                                    late.put(record.getUserId(), availableTimes);
                                } else {
                                    calcVO.setAbsenceTotal(calcVO.getAbsenceTotal() + minutes);
                                }
                            }
                        }
                    }
                });
            }
        });

        List<AtteCalcVO> result = new ArrayList<>();
        for (Long userId : users.keySet()) {
            AtteCalcVO calc = users.get(userId);
            getApplyHours(calc);
            result.add(calc);
        }
        return result;
    }

    @Override
    public QsResult record(AtteRecordVO atteRecordVO) {
        LocalDateTime now = LocalDateTime.ofInstant(atteRecordVO.getNow().toInstant(), ZoneId.systemDefault());
        int year = now.getYear();
        int month = now.getMonth().getValue();
        int day = now.getDayOfMonth();
        // 判断计算打卡的日期
        AtteConfigDO dailyUpdateTimeConfig = atteConfigMapper.selectOne(new LambdaQueryWrapper<AtteConfigDO>()
                .eq(AtteConfigDO::getConfigCode, "DailyUpdateTime"));
        String dailyUpdateTimeStr = String.format("%s-%s-%s %s:00", year, String.format("%02d", month), String.format("%02d", day),
                dailyUpdateTimeConfig.getConfigValue());
        LocalDateTime dailyUpdateTime = LocalDateTime.parse(dailyUpdateTimeStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        if (now.isBefore(dailyUpdateTime)) {
            year = now.minusDays(1).getYear();
            month = now.minusDays(1).getMonth().getValue();
            day = now.minusDays(1).getDayOfMonth();
        }

        // 查询已有记录
        AtteRecordDO atteRecordDO = atteRecordMapper.selectOne(new LambdaQueryWrapper<AtteRecordDO>()
                .eq(AtteRecordDO::getAtteYear, year)
                .eq(AtteRecordDO::getAtteMonth, month)
                .eq(AtteRecordDO::getAtteDay, day)
                .eq(AtteRecordDO::getUserId, atteRecordVO.getUserId()));
        // 当天第一次打卡同时插入上班打卡时间和下班打卡时间, 方便后续计算
        if (atteRecordDO == null) {
            atteRecordDO = new AtteRecordDO();
            atteRecordDO.setUserId(atteRecordVO.getUserId());
            atteRecordDO.setUserName(atteRecordVO.getUserName());
            atteRecordDO.setAtteYear(year);
            atteRecordDO.setAtteMonth(month);
            atteRecordDO.setAtteDay(day);
            atteRecordDO.setStartTime(Date.from(now.atZone(ZoneId.systemDefault()).toInstant()));
            atteRecordDO.setEndTime(Date.from(now.atZone(ZoneId.systemDefault()).toInstant()));
            atteRecordMapper.insert(atteRecordDO);
        } else {
            atteRecordDO.setEndTime(Date.from(now.atZone(ZoneId.systemDefault()).toInstant()));
            atteRecordMapper.updateById(atteRecordDO);
        }
        return QsResult.ok();
    }

    @Override
    public void result(AtteDateVO atteDateVO) {
        int year;
        int month;
        int day;
        if (atteDateVO.getYear() != null && atteDateVO.getMonth() != null) {
            year = atteDateVO.getYear();
            month = atteDateVO.getMonth();
            day = atteDateVO.getDay();
        } else {
            // 生成前一天结果
            LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault());
            LocalDateTime yesterday = now.minusDays(1);
            year = yesterday.getYear();
            month = yesterday.getMonth().getValue();
            day = yesterday.getDayOfMonth();
        }

        LocalDate date = LocalDate.of(year, month, day);
        AtteDailyTime daily = new AtteDailyTime(date);
        if (daily.getWorkTime().size() == 0) {
            // 无上班时间视为休息
            return;
        }

        // 查询当天的所有记录
        List<AtteRecordDO> atteRecords = atteRecordMapper.selectRecords(year, month, day, atteDateVO.getUserId());
        // 遍历生成考勤结果
        atteRecords.forEach(record -> {
            record.setAtteYear(year);
            record.setAtteMonth(month);
            record.setAtteDay(day);
            TimeSlot workTime = getWorkTimeSlot(record, daily);
            // 统计考勤结果
            setResult(record, workTime, daily);
            // 如果无考勤记录时插入结果
            if (record.getId() == null) {
                atteRecordMapper.insert(record);
            } else {
                atteRecordMapper.updateById(record);
            }
        });
    }

    @Override
    public void export(AtteDateVO atteDateVO, HttpServletResponse response) {
        int year;
        int month;
        if (atteDateVO.getYear() != null && atteDateVO.getMonth() != null) {
            year = atteDateVO.getYear();
            month = atteDateVO.getMonth();
        } else {
            // 生成当月结果
            LocalDateTime now = LocalDateTime.now(ZoneId.systemDefault());
            year = now.getYear();
            month = now.getMonth().getValue();
        }
        // 统计当月总工时
        Double total = queryTotal(atteDateVO);
        // 计算当月考勤汇总结果
        AtteCalcVO atteCalcVO = new AtteCalcVO();
        atteCalcVO.setUserId(atteDateVO.getUserId());
        atteCalcVO.setYear(atteDateVO.getYear());
        atteCalcVO.setMonth(atteDateVO.getMonth());
        List<AtteCalcVO> list = calc(atteCalcVO);
        List<AtteCalcExportVO> exportData = ConvertUtil.listCopy(list, AtteCalcExportVO.class);
        exportData.forEach(item -> item.setTotal(total));
        ServletOutputStream sos = null;
        try {
            String fileName = String.format("%s年%s月考勤记录", year, month);
            String name = URLEncoder.encode(fileName + ".xlsx", StandardCharsets.UTF_8);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
            response.setHeader("Content-disposition", "attachment;filename=" + name + ";" + "filename*=utf-8''" + name);

            String fullPath = exportPath + File.separator + fileName + ".xlsx";
            EasyExcel.write(fullPath, AtteCalcExportVO.class).sheet(fileName).doWrite(exportData);
            logger.info(String.format("导出路径: %s", fullPath));
            InputStream in = Files.newInputStream(Paths.get(fullPath));
            byte[] buffer = new byte[in.available()];
            int res = 1;
            while (res > 0) {
                res = in.read(buffer);
            }
            in.close();
            sos = response.getOutputStream();
            sos.write(buffer);
        } catch (IOException e) {
            logger.error("导出异常", e.getMessage(), e);
        } finally {
            try {
                if (sos != null) {
                    sos.flush();
                    sos.close();
                }
            } catch (IOException e) {
                logger.error("导出流关闭异常", e.getMessage(), e);
            }
        }
    }

    @Override
    public void update(AtteRecordDO atteRecordDO) {
        AtteRecordDO oldRecord = atteRecordMapper.selectOne(new LambdaQueryWrapper<AtteRecordDO>()
                .eq(AtteRecordDO::getUserId, atteRecordDO.getUserId())
                .eq(AtteRecordDO::getAtteYear, atteRecordDO.getAtteYear())
                .eq(AtteRecordDO::getAtteMonth, atteRecordDO.getAtteMonth())
                .eq(AtteRecordDO::getAtteDay, atteRecordDO.getAtteDay()));
        if (oldRecord != null) {
            AtteRecordDO newRecord = new AtteRecordDO();
            newRecord.setId(oldRecord.getId());
            if (atteRecordDO.getStartTime() != null) {
                newRecord.setStartTime(atteRecordDO.getStartTime());
            }
            if (atteRecordDO.getEndTime() != null) {
                newRecord.setEndTime(atteRecordDO.getEndTime());
            }
            atteRecordMapper.updateById(newRecord);
            // 生成结果
            LocalDate date = LocalDate.of(atteRecordDO.getAtteYear(), atteRecordDO.getAtteMonth(), atteRecordDO.getAtteDay());
            LocalDate now = LocalDate.now();
            if (date.isBefore(now)) {
                AtteDateVO atteDateVO = new AtteDateVO();
                atteDateVO.setUserId(atteRecordDO.getUserId());
                atteDateVO.setYear(date.getYear());
                atteDateVO.setMonth(date.getMonth().getValue());
                atteDateVO.setDay(date.getDayOfMonth());
                result(atteDateVO);
            }
        }
    }
}
